package com.dq.mybatis.core;

import java.io.IOException;
import java.io.InputStream;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java. util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

public class SqlSessionFactory {
	private MyBatisConfig config = null;
	//以文件中的命名空间 .id值为键

	private Map<String, MapperInfo> mapperInfos = new HashMap<String, MapperInfo>();
	/**
	 *@param config mybatis-config.xml酉己置文件路径
	 */

	public SqlSessionFactory(String configPath) {
		config = new MyBatisConfig(configPath);
		init(); //解析mapper文件
	}

	@SuppressWarnings("unchecked")
	private void init() {
		List<String> mappers = config.getMappers();
		if (mappers == null || mappers.isEmpty()){ //说明用户没有配置映射文件路径
			return;
		}

		SAXReader read = null;
		MapperInfo mapperInfo = null;
		Document doc = null;
		XPath xpath = null;
		List<Element> nodes = null;

		String basePath = "";// 存放基址路径，即namespace中的值
		String nodeName = null; //节点名
		String sql = null; // 尹妈语句
		List<String> paramNames = null;
		Pattern pattern = null;
		Matcher matcher = null;

		for (String mapper : mappers) {//循环解析这些配置文件
			try (InputStream is = this.getClass().getClassLoader().getResourceAsStream(mapper)) {
				read = new SAXReader();
				doc = read.read(is);

				basePath = doc.getRootElement().attributeValue("namespace"); // 取出根兀素中的namespace属性的属性值

				if (basePath != null && !"".equals(basePath)) {
					basePath +=".";// 后面就要接id属性
				}

				xpath = doc.createXPath("/mapper/*");
				nodes = xpath.selectNodes(doc);

				for (Element el : nodes) {
					mapperInfo = new MapperInfo();
					nodeName = el.getName (); // insert、select、delete、update

					if ("select".equalsIgnoreCase(nodeName)) { //说明是查询
						mapperInfo.setUpdate(false); //说明不是更新操作
						mapperInfo.setResultType(el.attributeValue("resultType"));
					}

					mapperInfo.setParameterType(el.attributeValue("parameterType"));
					sql = el.getTextTrim();

					//将sql语句中的 #{} 找出来，取出#{val}中的val存放到paramNames，然后中 #{}替换成?
					pattern = Pattern.compile("[#][{]\\w+}");
					matcher = pattern .matcher (sql); //从sql中查找满足条件的字符串

					paramNames = new ArrayList<String>();
					while (matcher.find()) {
						paramNames. add (matcher.group().replaceAll("[#{}]*",""));
					}
					mapperInfo.setParams(paramNames);

					sql = matcher. replaceAll("?");
					mapperInfo.setSql(sql);

					mapperInfos.put(basePath + el.attributeValue("id"), mapperInfo);
				}
			} catch (IOException e) {
				e.printStackTrace();
			} catch (DocumentException e) {
				e.printStackTrace();
			}
		}
	}
	
	public MyBatisConfig getConfig() {
		return config;
	}
	
	public Map<String, MapperInfo> getMapperlnfos(){
		return mapperInfos;
	}
	
	public MapperInfo getMapperlnfo(String id) {
		return mapperInfos.getOrDefault(id, null);
	}
}